package settings;

import robot.ExecutionRobot;

import java.awt.datatransfer.*;
import java.io.*;
import java.util.*;

/**
 * Represents information used for running a series of Command objects.
 * @author BDS
 */
public class Workflow implements Serializable, Transferable
{
	private static final long serialVersionUID = 1L;

	private UUID id;
	private String name;
	private int iterations;
	private String description;
	private List<Command> commands;

	/**
	 * Class constructor.
	 */
	public Workflow()
	{
		id = UUID.randomUUID();
		name = "New workflow";
		iterations = 1;
		description = "";
		commands = new ArrayList<Command>();
	}
	
	/**
	 * Copy constructor.
	 * @param workflow The Workflow to copy.
	 */
	public Workflow(Workflow workflow)
	{
		id = UUID.randomUUID();
		name = workflow.getName();
		iterations = workflow.getIterations();
		description = workflow.getDescription();
		commands = new ArrayList<Command>(workflow.getCommands().size());
		for (Command command : workflow.getCommands())
		{
			commands.add(new Command(command));
		}
	}

	/**
	 * Returns a String specific to the name.
	 * @return A String specific to the name.
	 */
	@Override
	public String toString() 
	{ 
		return name;
	}

	/**
	 * Indicates whether the given Object is equivalent.
	 * @param workflow Object to compare.
	 * @return True if the Object is equal; false otherwise.
	 */
	@Override
	public boolean equals(Object workflow)
	{
		boolean equals = false;

		if ((workflow instanceof Workflow))
		{
			equals = id.equals(((Workflow) workflow).getID());
		}

		return equals;
	}
	
	/**
	 * Returns the hash code.
	 * @return The hash code.
	 */
	@Override
	public int hashCode()
	{
		int hashCode = 23;

	    hashCode = hashCode * 37 + id.hashCode();
	    hashCode = hashCode * 37 + name.hashCode();
	    hashCode = hashCode * 37 + new Integer(iterations).hashCode();
	    hashCode = hashCode * 37 + description.hashCode();
	    
	    for (Command command : commands)
	    {
	    	 hashCode = hashCode * 37 + command.hashCode();
	    }
	    
	    return hashCode;
	}
	
	/**
	 * Getter for the transferable data.
	 */
	@Override
	public Object getTransferData(DataFlavor dataFlavor) throws UnsupportedFlavorException, IOException
	{
		return this;
	}

	/**
	 * Getter for the supported transferable data flavors.
	 */
	@Override
	public DataFlavor[] getTransferDataFlavors()
	{
		return new DataFlavor[] { DataFlavor.stringFlavor };
	}

	/**
	 * Determines if the given DataFlavor is supported.
	 */
	@Override
	public boolean isDataFlavorSupported(DataFlavor dataFlavor)
	{
		return dataFlavor.equals(DataFlavor.stringFlavor);
	}

	/**
	 * Executes all Command objects for this Environment.
	 * @return True if successful; false otherwise.
	 */
	public boolean execute(ExecutionRobot executionRobot)
	{
		for (int i = 0; i < iterations; i++)
		{
			executionRobot.setCurrentIteration(executionRobot.getCurrentIteration() + 1);
			for (Command command : commands)
			{
				if (!command.execute(executionRobot))
				{
					return false;
				}
			}
		}
		executionRobot.setCurrentIteration(0);
		
		return true;
	}
	
	/**
	 * Getter for the ID.
	 * @return The ID.
	 */
	public UUID getID() { return id; }

	/**
	 * Getter for the name.
	 * @return The name.
	 */
	public String getName() { return name; }
	
	/**
	 * Setter for the name.
	 * @param name The name.
	 */
	public void setName(String name) { this.name = name; }
	
	/**
	 * Getter for the iterations.
	 * @return The iterations.
	 */
	public int getIterations() { return iterations; }
	
	/**
	 * Setter for the iterations.
	 * @param iterations The name.
	 */
	public void setIterations(int iterations) { this.iterations = iterations; }	

	/**
	 * Getter for the description.
	 * @return The description.
	 */
	public String getDescription() { return description; }
	
	/**
	 * Setter for the description.
	 * @param description The description.
	 */
	public void setDescription(String description) { this.description = description; }
	
	/**
	 * Getter for the Command collection.
	 * @return The Command collection.
	 */
	public List<Command> getCommands() { return commands; }

	/**
	 * Setter for the Command collection.
	 * @param commands The Command collection.
	 */
	public void setCommands(List<Command> commands) { this.commands = commands; }
}
